Deploying Cocoa applications
(this page is obsolete, since deployment is now a built-in feature of recent CHICKEN versions)
Similar to the solution for Deploying Linux binaries, we can modify the link-paths of a Scheme application that uses the objc egg to create a fully self-contained Cocoa application bundle.
First, build the "Temperature Converter" application, but adding a small prologue that retrieves the physical location of the current executable and sets the "repository path", the path where extensions are to be loaded at run-time:
% cd tests/Temperature\ Converter.app/Contents/MacOS % csc -X objc -O2 -o "TemperatureConverter" temp-converter.scm -v -framework CoreFoundation -prologue osx-deploy-bundle.scm
The prologue code looks like this:
;;;; osx-deploy-bundle.scm ; ; Use like this: ; ; % csc <your-application-main-module> -prologue osx-deploy-bundle.scm -framework CoreFoundation (use utils) #> #include <CoreFoundation/CoreFoundation.h> <# #>! static char *get_bundle_path() { CFBundleRef bundle = CFBundleGetMainBundle(); CFURLRef url = CFBundleCopyExecutableURL(bundle); static char buffer[ 256 ]; if(CFURLGetFileSystemRepresentation(url, true, buffer, sizeof(buffer))) return buffer; else return NULL; } <# (let ((application-path (get_bundle_path))) (assert application-path "unable to compute executable path") (repository-path (pathname-directory application-path) ) )
After building the application in the objc egg, we can look at the libraries that are used at run-time:
% otool -L TemperatureConverter TemperatureConverter: /usr/lib/libchicken.0.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.0.0) /usr/lib/libffi.4.dylib (compatibility version 5.0.0, current version 5.1.0)
Then we use install_name_tool to change the load-paths of the two non-system libraries to point to the location where the executable (TemperatureConverter) is located:
% install_name_tool -change /usr/lib/libchicken.0.dylib @executable_path/libchicken.0.dylib \ -change /usr/lib/libffi.4.dylib @executable_path/libffi.4.dylib TemperatureConverter % otool -L TemperatureConverter TemperatureConverter: @executable_path/libchicken.0.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.0.0) @executable_path/libffi.4.dylib (compatibility version 5.0.0, current version 5.1.0)
Now copy the required libraries and the compiled extensions into the directory, for Temperature Converter, you'll need the following:
- Runtime libraries: libchicken.0.dylib libffi.4.dylib, usually located in /usr/lib, or wherever you have installed them.
- Extensions: objc-class-proxies-bin.so objc-class-proxies.so objc-support.so cocoa.so, located in your repository-path (run csi -p "(repository-path)" to find it).
Now you application is complete - the whole Temperature Converter.app bundle can be moved to a machine that doesn't have CHICKEN or the objc egg installed.
To verify this, run it with the Console application open:
% DYLD_PRINT_LIBRARIES=1 open Temperature\ Converter.app/ ===== Friday, April 21, 2006 10:24:06 PM Europe/Berlin ===== dyld: loaded: /Users/felix/tmp/t2old/Temperature Converter.app/Contents/MacOS/TemperatureConverter dyld: loaded: /Users/felix/tmp/t2old/Temperature Converter.app/Contents/MacOS/libchicken.0.dylib dyld: loaded: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation dyld: loaded: /usr/lib/libSystem.B.dylib, cpu-sub-type: 0 dyld: loaded: /Users/felix/tmp/t2old/Temperature Converter.app/Contents/MacOS/libffi.4.dylib ... dyld: loaded: /Users/felix/tmp/t2old/Temperature Converter.app/Contents/MacOS/objc-support.so ... dyld: loaded: /Users/felix/tmp/t2old/Temperature Converter.app/Contents/MacOS/objc-class-proxies.so dyld: loaded: /Users/felix/tmp/t2old/Temperature Converter.app/Contents/MacOS/objc-class-proxies-bin.so dyld: loaded: /Users/felix/tmp/t2old/Temperature Converter.app/Contents/MacOS/cocoa.so ... convertToFar: called; sender #<objc-instance <NSButton: 0x21327d0>>